<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 15.7.&nbsp; Message Queues</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch15lev1sec6.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch15lev1sec8.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top"><a name="ch15lev1sec7"></a>
<h3 class="docSection1Title">15.7. Message Queues</h3>
<p class="docText">A message queue is a linked list of messages stored within the kernel and identified by a message queue identifier. We'll call the message queue just a <span class="docEmphasis">queue</span> and its identifier a <span class="docEmphasis">queue ID</span>.</P>
<blockquote>
<p class="docText">The Single UNIX Specification includes an alternate IPC message queue implementation in the message-passing option of its real-time extensions. We do not cover the real-time extensions in this text.</P>
</blockquote>
<p class="docText">A new queue is created or an existing queue opened by <tt>msgget</tt>. New messages are added to the end of a queue by <tt>msgsnd</tt>. Every message has a positive long integer <a name="idd1e113924"></a><a name="idd1e113927"></a><a name="idd1e113930"></a><a name="idd1e113933"></a><a name="idd1e113938"></a><a name="idd1e113943"></a><a name="idd1e113946"></a>type field, a non-negative length, and the actual data bytes (corresponding to the length), all of which are specified to <tt>msgsnd</tt> when the message is added to a queue. Messages are fetched from a queue by <tt>msgrcv</tt>. We don't have to fetch the messages in a first-in, first-out order. Instead, we can fetch messages based on their type field.</p>
<p class="docText">Each queue has the following <tt>msqid_ds</tt> structure associated with it:</P>

<pre>
   struct msqid_ds {
     struct ipc_perm  msg_perm;     /* see Section 15.6.2 */
     msgqnum_t        msg_qnum;     /* # of messages on queue */
     msglen_t         msg_qbytes;   /* max # of bytes on queue */
     pid_t            msg_lspid;    /* pid of last msgsnd() */
     pid_t            msg_lrpid;    /* pid of last msgrcv() */
     time_t           msg_stime;    /* last-msgsnd() time */
     time_t           msg_rtime;    /* last-msgrcv() time */
     time_t           msg_ctime;    /* last-change time */
     .
     .
     .
   };
</pre><BR>

<p class="docText">This structure defines the current status of the queue. The members shown are the ones defined by the Single UNIX Specification. Implementations include additional fields not covered by the standard.</P>
<p class="docText"><a class="docLink" href="#ch15fig26">Figure 15.26</a> lists the system limits that affect message queues. We show &quot;notsup&quot; where the platform doesn't support the feature. We show &quot;derived&quot; whenever a limit is derived from other limits. For example, the maximum number of messages in a Linux system is based on the maximum number of queues and the maximum amount of data allowed on the queues. If the minimum message size is 1 byte, that would limit the number of messages systemwide to <span class="docEmphasis">maximum # queues * maximum size of a queue</span>. Given the limits in <a class="docLink" href="#ch15fig26">Figure 15.26</a>, Linux has an upper bound of 262,144 messages with the default configuration. (Even though a message can contain zero bytes of data, Linux treats it as if it contained 1 byte, to limit the number of messages queued.)</p>
<a name="ch15fig26"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><H5 class="docTableTitle">Figure 15.26. System limits that affect message queues</H5></caption><colgroup><col width="300"><col width="50"><col width="50"><col width="60"><col width="50"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle" rowspan="2"><p class="docText"><span class="docEmphRoman">Description</span></P></th><th class="bottomBorder thead" scope="col" align="center" valign="top" colspan="4"><p class="docText"><span class="docEmphRoman">Typical values</span></p></th></TR><TR><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="bottom"><p class="docText"><span class="docEmphRoman">FreeBSD 5.2.1</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="bottom"><p class="docText"><span class="docEmphRoman">Linux 2.4.22</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="bottom"><p class="docText"><span class="docEmphRoman">Mac OS X 10.3</span></P></th><th class="bottomBorder thead" scope="col" align="center" valign="bottom"><p class="docText"><span class="docEmphRoman">Solaris 9</span></P></th></tr></thead><TR><TD class="rightBorder" align="left" valign="top"><p class="docText">Size in bytes of largest message we can send</p></td><td class="rightBorder" align="right" valign="top"><p class="docText">16,384</p></TD><td class="rightBorder" align="right" valign="top"><p class="docText">8,192</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">notsup</p></td><td class="docTableCell" align="right" valign="top"><p class="docText">2,048</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText">The maximum size in bytes of a particular queue (i.e., the sum of all the messages on the queue)</p></td><td class="rightBorder" align="right" valign="top"><p class="docText">2,048</p></td><td class="rightBorder" align="right" valign="top"><p class="docText">16,384</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">notsup</P></TD><td class="docTableCell" align="right" valign="top"><p class="docText">4,096</P></TD></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText">The maximum number of messages queues, systemwide</P></TD><td class="rightBorder" align="right" valign="top"><p class="docText">40</P></td><TD class="rightBorder" align="right" valign="top"><p class="docText">16</P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">notsup</P></TD><td class="docTableCell" align="right" valign="top"><p class="docText">50</P></TD></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText">The maximum number of messages, systemwide</p></TD><td class="rightBorder" align="right" valign="top"><p class="docText">40</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">derived</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">notsup</p></td><td class="docTableCell" align="right" valign="top"><p class="docText">40</p></td></tr></table></p><br>
<blockquote>
<p class="docText">Recall from <a class="docLink" href="ch15lev1sec1.html#ch15fig01">Figure 15.1</a> that Mac OS X 10.3 doesn't support XSI message queues. Since Mac OS X is based in part on FreeBSD, and FreeBSD supports message queues, it is possible for Mac OS X to support them, too. Indeed, a good Internet search engine will provide pointers to a third-party port of XSI message queues for Mac OS X.</p>
</blockquote>
<p class="docText">The first function normally called is <tt>msgget</tt> to either open an existing queue or create a new queue.</p>
<a name="inta164"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText"><a name="idd1e114169"></a><a name="idd1e114174"></a><a name="idd1e114179"></a><a name="idd1e114184"></a><a name="idd1e114189"></a><a name="idd1e114194"></a><a name="idd1e114199"></a><a name="idd1e114204"></a><a name="idd1e114209"></a><a name="idd1e114212"></a><a name="idd1e114217"></a><a name="idd1e114224"></a><a name="idd1e114231"></a><a name="idd1e114236"></a><a name="idd1e114241"></a>
<pre>
#include &lt;sys/msg.h&gt;

int msgget(key_t <span class="docEmphItalicAlt">key</span>, int <span class="docEmphItalicAlt">flag</span>);
</pre><br>

</P></TD></tr><TR><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: message queue ID if OK, 1 on error</P></td></TR></table></P><BR>
<p class="docText">In <a class="docLink" href="ch15lev1sec6.html#ch15lev2sec1">Section 15.6.1</a>, we described the rules for converting the <span class="docEmphasis">key</span> into an identifier and discussed whether a new queue is created or an existing queue is referenced. When a new queue is created, the following members of the <tt>msqid_ds</tt> structure are initialized.</p>
<UL><li><p class="docList">The <tt>ipc_perm</tt> structure is initialized as described in <a class="docLink" href="ch15lev1sec6.html#ch15lev2sec2">Section 15.6.2</a>. The <tt>mode</tt> member of this structure is set to the corresponding permission bits of <span class="docEmphasis">flag</span>. These permissions are specified with the values from <a class="docLink" href="ch15lev1sec6.html#ch15fig24">Figure 15.24</a>.</P></LI><LI><p class="docList"><tt>msg_qnum</tt>, <tt>msg_lspid</tt>, <tt>msg_lrpid</tt>, <tt>msg_stime</tt>, and <tt>msg_rtime</tt> are all set to 0.</p></LI><LI><p class="docList"><tt>msg_ctime</tt> is set to the current time.</p></LI><LI><p class="docList"><tt>msg_qbytes</tt> is set to the system limit.</p></li></ul>
<p class="docText">On success, <tt>msgget</tt> returns the non-negative queue ID. This value is then used with the other three message queue functions.</p>
<p class="docText">The <tt>msgctl</tt> function performs various operations on a queue. This function and the related functions for semaphores and shared memory (<tt>semctl</tt> and <tt>shmctl</tt>) are the <tt>ioctl</tt>-like functions for XSI IPC (i.e., the garbage-can functions).</P>
<a name="inta165"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><TR><td class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
#include &lt;sys/msg.h&gt;

int msgctl(int <span class="docEmphItalicAlt">msqid</span>, int <span class="docEmphItalicAlt">cmd</span>, struct msqid_ds *<span class="docEmphItalicAlt">buf</span> );
</pre><BR>

</p></td></tr><tr><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: 0 if OK, 1 on error</p></td></tr></table></p><br>
<p class="docText">The <span class="docEmphasis">cmd</span> argument specifies the command to be performed on the queue specified by <span class="docEmphasis">msqid</span>.</p>
<p><table cellspacing="0" FRAME="void" RULES="none" cellpadding="5"><colgroup><col width="100"><col width="400"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText"><tt>IPC_STAT</tt></p></td><td class="docTableCell" align="left" valign="top"><p class="docText">Fetch the <tt>msqid_ds</tt> structure for this queue, storing it in the structure pointed to by <span class="docEmphasis">buf</span>.</P></TD></tr><TR><TD class="docTableCell" align="left" valign="top"><p class="docText"><tt>IPC_SET</tt></P></td><TD class="docTableCell" align="left" valign="top"><p class="docText">Copy the following fields from the structure pointed to by <span class="docEmphasis">buf</span> to the <tt>msqid_ds</tt> structure associated with this queue: <tt>msg_perm.uid</tt>, <tt>msg_perm.gid</tt>, <tt>msg_perm.mode</tt>, and <tt>msg_qbytes</tt>. This command can be executed only by a process whose effective user ID equals <tt>msg_perm.cuid</tt> or <tt>msg_perm.uid</tt> or by a process with superuser privileges. Only the superuser can increase the value of <tt>msg_qbytes</tt>.</P></TD></tr><TR><td class="docTableCell" align="left" valign="top"><p class="docText"><tt>IPC_RMID</tt></P></TD><TD class="docTableCell" align="left" valign="top"><p class="docText">Remove the message queue from the system and any data still on the queue. This removal is immediate. Any other process still using the message queue will get an error of <tt>EIDRM</tt> on its next attempted operation on the queue. This command can be executed only by a process whose effective user ID equals <tt>msg_perm.cuid</tt> or <tt>msg_perm.uid</tt> or by a process with superuser privileges.</p></TD></TR></table></p><BR>
<p class="docText"><a name="idd1e114497"></a><a name="idd1e114502"></a><a name="idd1e114507"></a><a name="idd1e114512"></a><a name="idd1e114517"></a><a name="idd1e114524"></a>We'll see that these three commands (<tt>IPC_STAT</tt>, <tt>IPC_SET</tt>, and <tt>IPC_RMID</tt>) are also provided for semaphores and shared memory.</P>
<p class="docText">Data is placed onto a message queue by calling <tt>msgsnd</tt>.</p>
<a name="inta167"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID3"></a><div class="v1"><a href="ch15lev1sec7.html#PLID3">[View full width]</a></div><pre>
#include &lt;sys/msg.h&gt;

int msgsnd(int <span class="docEmphItalicAlt">msqid</span>, const void *<span class="docEmphItalicAlt">ptr</span>, size_t
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> <span class="docEmphItalicAlt">nbytes</span>, int <span class="docEmphItalicAlt">flag</span>);
</pre><BR>

</p></TD></tr><TR><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: 0 if OK, 1 on error</p></td></tr></table></p><br>
<p class="docText">As we mentioned earlier, each message is composed of a positive long integer type field, a non-negative length (<span class="docEmphasis">nbytes</span>), and the actual data bytes (corresponding to the length). Messages are always placed at the end of the queue.</p>
<p class="docText">The <span class="docEmphasis">ptr</span> argument points to a long integer that contains the positive integer message type, and it is immediately followed by the message data. (There is no message data if <span class="docEmphasis">nbytes</span> is 0.) If the largest message we send is 512 bytes, we can define the following structure:</p>

<pre>
   struct mymesg {
     long  mtype;      /* positive message type */
     char  mtext[512]; /* message data, of length <span class="docEmphItalicAlt">nbytes</span> */
   };
</pre><br>

<p class="docText">The <span class="docEmphasis">ptr</span> argument is then a pointer to a <tt>mymesg</tt> structure. The message type can be used by the receiver to fetch messages in an order other than first in, first out.</p>
<blockquote>
<p class="docText">Some platforms support both 32-bit and 64-bit environments. This affects the size of long integers and pointers. For example, on 64-bit SPARC systems, Solaris allows both 32-bit and 64-bit applications to coexist. If a 32-bit application were to exchange this structure over a pipe or a socket with a 64-bit application, problems would arise, because the size of a long integer is 4 bytes in a 32-bit application, but 8 bytes in a 64-bit application. This means that a 32-bit application will expect that the <tt>mtext</tt> field will start 4 bytes after the start of the structure, whereas a 64-bit application will expect the <tt>mtext</tt> field to start 8 bytes after the start of the structure. In this situation, part of the 64-bit application's <tt>mtype</tt> field will appear as part of the <tt>mtext</tt> field to the 32-bit application, and the first 4 bytes in the 32-bit application's <tt>mtext</tt> field will be interpreted as a part of the <tt>mtype</tt> field by the 64-bit application.</p>
<p class="docText">This problem doesn't happen with XSI message queues, however. Solaris implements the 32-bit version of the IPC system calls with different entry points than the 64-bit version of the IPC system calls. The system calls know how to deal with a 32-bit application communicating with a 64-bit application, and treat the type field specially to avoid it interfering with the data portion of the message. The only potential problem is a loss of information when a 64-bit application sends a message with a value in the 8-byte type field that is larger than will fit in a 32-bit application's 4-byte type field. In this case, the 32-bit application will see a truncated type value.</p>
</blockquote>
<p class="docText">A <span class="docEmphasis">flag</span> value of <tt>IPC_NOWAIT</tt> can be specified. This is similar to the nonblocking I/O flag for file I/O (<a class="docLink" href="ch14lev1sec2.html#ch14lev1sec2">Section 14.2</a>). If the message queue is full (either the total number of messages on the queue equals the system limit, or the total number of bytes on the queue equals the system limit), specifying <tt>IPC_NOWAIT</tt> causes <tt>msgsnd</tt> to return immediately with an error of <tt>EAGAIN</tt>. If <tt>IPC_NOWAIT</tt> is not specified, we are blocked until there is room for the message, the queue is removed from the system, or a signal is caught and the signal handler returns. In the second case, an error of <tt>EIDRM</tt> is returned (&quot;identifier removed&quot;); in the last case, the error returned is <tt>EINTR</tt>.</p>
<p class="docText"><a name="idd1e114673"></a><a name="idd1e114678"></a><a name="idd1e114683"></a><a name="idd1e114688"></a><a name="idd1e114693"></a><a name="idd1e114698"></a><a name="idd1e114705"></a>Note how ungracefully the removal of a message queue is handled. Since a reference count is not maintained with each message queue (as there is for open files), the removal of a queue simply generates errors on the next queue operation by processes still using the queue. Semaphores handle this removal in the same fashion. In contrast, when a file is removed, the file's contents are not deleted until the last open descriptor for the file is closed.</p>
<p class="docText">When <tt>msgsnd</tt> returns successfully, the <tt>msqid_ds</tt> structure associated with the message queue is updated to indicate the process ID that made the call (<tt>msg_lspid</tt>), the time that the call was made (<tt>msg_stime</tt>), and that one more message is on the queue (<tt>msg_qnum</tt>).</p>
<p class="docText">Messages are retrieved from a queue by <tt>msgrcv</tt>.</p>
<a name="inta166"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><TR><TD class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID5"></a><div class="v1"><a href="ch15lev1sec7.html#PLID5">[View full width]</a></div><pre>
#include &lt;sys/msg.h&gt;

ssize_t msgrcv(int <span class="docEmphItalicAlt">msqid</span>, void *<span class="docEmphItalicAlt">ptr</span>, size_t <span class="docEmphItalicAlt">nbytes</span>
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif">, long <span class="docEmphItalicAlt">type</span>, int <span class="docEmphItalicAlt">flag</span>);
</pre><br>

</P></TD></TR><tr><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: size of data portion of message if OK, 1 on error</P></TD></tr></table></P><br>
<p class="docText">As with <tt>msgsnd</tt>, the <span class="docEmphasis">ptr</span> argument points to a long integer (where the message type of the returned message is stored) followed by a data buffer for the actual message data. <span class="docEmphasis">nbytes</span> specifies the size of the data buffer. If the returned message is larger than <span class="docEmphasis">nbytes</span> and the <tt>MSG_NOERROR</tt> bit in <span class="docEmphasis">flag</span> is set, the message is truncated. (In this case, no notification is given to us that the message was truncated, and the remainder of the message is discarded.) If the message is too big and this <span class="docEmphasis">flag</span> value is not specified, an error of <tt>E2BIG</tt> is returned instead (and the message stays on the queue).</P>
<p class="docText">The <span class="docEmphasis">type</span> argument lets us specify which message we want.</P>
<P><table cellspacing="0" FRAME="void" RULES="none" cellpadding="5"><colgroup><col width="100"><col width="400"></colgroup><thead></thead><tr><TD class="docTableCell" align="left" valign="top"><p class="docText"><span class="docEmphasis">type</span> == 0</P></td><TD class="docTableCell" align="left" valign="top"><p class="docText">The first message on the queue is returned.</P></td></tr><tr><td class="docTableCell" align="left" valign="top"><p class="docText"><span class="docEmphasis">type</span> &gt; 0</P></td><TD class="docTableCell" align="left" valign="top"><p class="docText">The first message on the queue whose message type equals <span class="docEmphasis">type</span> is returned.</p></TD></tr><tr><td class="docTableCell" align="left" valign="top"><p class="docText"><span class="docEmphasis">type</span> &lt; 0</p></td><td class="docTableCell" align="left" valign="top"><p class="docText">The first message on the queue whose message type is the lowest value less than or equal to the absolute value of <span class="docEmphasis">type</span> is returned.</p></td></tr></table></p><br>
<p class="docText">A nonzero <span class="docEmphasis">type</span> is used to read the messages in an order other than first in, first out. For example, the <span class="docEmphasis">type</span> could be a priority value if the application assigns priorities to the messages. Another use of this field is to contain the process ID of the client if a single message queue is being used by multiple clients and a single server (as long as a process ID fits in a long integer).</p>
<p class="docText">We can specify a <span class="docEmphasis">flag</span> value of <tt>IPC_NOWAIT</tt> to make the operation nonblocking, causing <tt>msgrcv</tt> to return -1 with <tt>errno</tt> set to <tt>ENOMSG</tt> if a message of the specified type is not available. If <tt>IPC_NOWAIT</tt> is not specified, the operation blocks until a message of the specified type is available, the queue is removed from the system (-1 is returned with <tt>errno</tt> set to <tt>EIDRM</tt>), or a signal is caught and the signal handler returns (causing <tt>msgrcv</tt> to return 1 with <tt>errno</tt> set to <tt>EINTR</tt>).</p>
<p class="docText">When <tt>msgrcv</tt> succeeds, the kernel updates the <tt>msqid_ds</tt> structure associated with the message queue to indicate the caller's process ID (<tt>msg_lrpid</tt>), the time of the call (<tt>msg_rtime</tt>), and that one less message is on the queue (<tt>msg_qnum</tt>).</p>
<a name="ch15ex11"></a>
<h5 class="docExampleTitle">ExampleTiming Comparison of Message Queues versus Stream Pipes</h5>
<p class="docText"><a name="idd1e114940"></a><a name="idd1e114945"></a><a name="idd1e114950"></a><a name="idd1e114955"></a><a name="idd1e114958"></a><a name="idd1e114963"></a><a name="idd1e114966"></a><a name="idd1e114969"></a><a name="idd1e114974"></a><a name="idd1e114977"></a><a name="idd1e114982"></a><a name="idd1e114987"></a><a name="idd1e114992"></a><a name="idd1e114997"></a>If we need a bidirectional flow of data between a client and a server, we can use either message queues or full-duplex pipes. (Recall from <a class="docLink" href="ch15lev1sec1.html#ch15fig01">Figure 15.1</a> that full-duplex pipes are available through the UNIX domain sockets mechanism (<a class="docLink" href="ch17lev1sec3.html#ch17lev1sec3">Section 17.3</a>), although some platforms provide a full-duplex pipe mechanism through the <tt>pipe</tt> function.)</p>
<p class="docText"><a class="docLink" href="#ch15fig27">Figure 15.27</a> shows a timing comparison of three of these techniques on Solaris: message queues, STREAMS-based pipes, and UNIX domain sockets. The tests consisted of a program that created the IPC channel, called <tt>fork</tt>, and then sent about 200 megabytes of data from the parent to the child. The data was sent using 100,000 calls to <tt>msgsnd</tt>, with a message length of 2,000 bytes for the message queue, and 100,000 calls to <tt>write</tt>, with a length of 2,000 bytes for the STREAMS-based pipe and UNIX domain socket. The times are all in seconds.</P>
<p class="docText">These numbers show us that message queues, originally implemented to provide higher-than-normal-speed IPC, are no longer that much faster than other forms of IPC (in fact, STREAMS-based pipes are faster than message queues). (When message queues were implemented, the only other form of IPC available was half-duplex pipes.) When we consider the problems in using message queues (<a class="docLink" href="ch15lev1sec6.html#ch15lev2sec4">Section 15.6.4</a>), we come to the conclusion that we shouldn't use them for new applications.</P>

<a name="ch15fig27"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><H5 class="docTableTitle">Figure 15.27. Timing comparison of IPC alternatives on Solaris</H5></caption><colgroup><col width="140"><col width="50"><col width="50"><col width="50"></colgroup><thead><TR><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Operation</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">User</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">System</span></P></th><th class="bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Clock</span></P></th></tr></thead><TR><td class="rightBorder" align="left" valign="top"><p class="docText">message queue</P></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">0.57</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">3.63</p></TD><TD class="docTableCell" align="center" valign="top"><p class="docText">4.22</p></td></tr><tr><TD class="rightBorder" align="left" valign="top"><p class="docText">STREAMS pipe</p></TD><td class="rightBorder" align="center" valign="top"><p class="docText">0.50</P></td><td class="rightBorder" align="center" valign="top"><p class="docText">3.21</p></td><td class="docTableCell" align="center" valign="top"><p class="docText">3.71</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText">UNIX domain socket</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">0.43</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">4.45</p></TD><TD class="docTableCell" align="center" valign="top"><p class="docText">5.59</p></TD></TR></table></P><br>

<a href="17021535.html"><img src="images/pixel.gif" alt="" width="1" height="1" border="0"></a><UL></UL></TD></tr></table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch15lev1sec6.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch15lev1sec8.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
</body></html><br>
<table width="100%" cellspacing="0" cellpadding="0"
style="margin-top: 0pt; border-collapse: collapse;"> 
<tr> <td align="right" style="background-color=white; border-top: 1px solid gray;"> 
<a href="http://www.zipghost.com/" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">The CHM file was converted to HTM by Trial version of <b>ChmD<!--90-->ecompiler</b>.</a>
</TD>
</TR><tr>
<td align="right" style="background-color=white; "> 
<a href="http://www.etextwizard.com/download/cd/cdsetup.exe" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">Download <b>ChmDec<!--90-->ompiler</b> at: http://www.zipghost.com</a>
</TD></tr></table>
